package java_thinking.unit_21._21_7;

import java.io.File;
import java.io.FileFilter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @Desc:   7-17 通过毒丸对象来关闭服务
 *          1.只有在无界队列中，毒丸对象才能可靠的工作
 * @author: cww
 * @DateTime: 2019-06-16 16:34
 */

public class IndexingService {
    private static final int CAPACITY = 1000;
     private static final File POISON = new File("");
    private final IndexerThread consumer = new IndexerThread();
    private final CrawlerThread producer = new CrawlerThread();
     private final BlockingQueue<File> queue;
     private final FileFilter fileFilter;
     private final File root;

    public IndexingService(final FileFilter fileFilter, File root) {
        this.fileFilter = new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() || fileFilter.accept(pathname);
            }
        };
        this.root = root;
        this.queue = new LinkedBlockingQueue<File>(CAPACITY);
    }
    private boolean alreadyIndexed(File f) {
        return false;
    }

    class CrawlerThread extends Thread {
        @Override
        public void run() {
            try {
                crawl(root);
            } catch (InterruptedException e) { /* fall through */
            } finally {
                while (true) {
                    try {
                        //catch到 InterruptedException 后放入毒丸
                        queue.put(POISON);
                        break;
                    } catch (InterruptedException e1) { /* retry */
                    }
                }
            }
        }

        private void crawl(File root) throws InterruptedException {
            File[] entries = root.listFiles(fileFilter);
            if (entries != null) {
                for (File entry : entries) {
                    if (entry.isDirectory())
                        crawl(entry);
                    else if (!alreadyIndexed(entry))
                        queue.put(entry);
                }
            }
        }
    }
    class IndexerThread extends Thread {
        @Override
        public void run() {
            try {
                while (true) {
                    File file = queue.take();
                    if (file == POISON)
                        break;
                    else
                        indexFile(file);
                }
            } catch (InterruptedException consumed) {
            }
        }

        public void indexFile(File file) {
            /*...*/
        };
    }

    public void start() {
        producer.start();
        consumer.start();
    }
    public void stop() {
        producer.interrupt();
    }
    public void awaitTermination() throws InterruptedException {
        consumer.join();
    }
}
